#pragma once

#include <vector>
#include "FCProperties.h"

namespace UIStone
{
	class FCController_Border : public FCPropertyContainer
		<
			Loki::TL::MakeTypelist
			<
				FCPropertyBorderWidth,
				FCPropertyBorderStyle,
				FCPropertyBorderColor
			>::Result
		>
	{
	private:
		struct FourWayBorderColor
		{
			COLORREF m_crTop;
			COLORREF m_crRight;
			COLORREF m_crBottom;
			COLORREF m_crLeft;
		};
 		typedef std::vector<FourWayBorderColor> FourWayBorderColorArray;

	public:
		FCController_Border()
		{
			DefaultValue();
		}

		virtual ~FCController_Border() {}

	public:
		void DrawBorder(CDC* pDC, LPRECT pRect)
		{
 			if (BorderWidth() > 0)
 			{
 				FourWayBorderColorArray::iterator i = m_arrayColors.begin();
 				if (i != m_arrayColors.end())
 				{
 					for (int j = 0; j < BorderWidth(); ++j)
 					{
 						// Draw Border
 						_drawBorder(pDC, pRect->left, pRect->top, pRect->right, pRect->bottom, *i);
 
 						// DeflateRect
 						++pRect->left;
 						++pRect->top;
 						--pRect->right;
 						--pRect->bottom;
 
 						FourWayBorderColorArray::iterator iNext = i;
 						if (++iNext != m_arrayColors.end())
 						{
 							i = iNext;
 						}
 					}
 				}
 			}
		}

		void ParseBorderColors()
		{
			m_arrayColors.clear();

			UINT nLength = BorderColor().length();
			BSTR szColors = BorderColor().GetBSTR();

			std::vector<int> arrayColors;
			std::wstring strValue;

			for (UINT i = 0; i < nLength; ++i)
			{
				switch(szColors[i])
				{
				case L' ':
					break;
				case L',':
					{
						if (!strValue.empty())
						{
							arrayColors.push_back(_wtoi(strValue.c_str()));
							strValue.clear();
						}
					}
					break;
				case L';':
					{
						if (!strValue.empty())
						{
							arrayColors.push_back(_wtoi(strValue.c_str()));
							strValue.clear();
						}

						switch(arrayColors.size())
						{
						case 0:
							break;
						case 1:
							{
								FourWayBorderColor color;
								color.m_crBottom = color.m_crLeft = color.m_crRight = color.m_crTop = arrayColors[0];
								m_arrayColors.push_back(color);
							}
							break;
						case 2:
							{
								FourWayBorderColor color;
								color.m_crLeft = color.m_crTop = arrayColors[0];
								color.m_crBottom = color.m_crRight = arrayColors[1];
								m_arrayColors.push_back(color);
							}
							break;
						case 3:
							{
								FourWayBorderColor color;
								color.m_crTop = arrayColors[0];
								color.m_crLeft = color.m_crRight = arrayColors[1];
								color.m_crBottom = arrayColors[2];
								m_arrayColors.push_back(color);
							}
						    break;
						default:
							{
								FourWayBorderColor color;
								color.m_crTop = arrayColors[0];
								color.m_crRight = arrayColors[1];
								color.m_crBottom = arrayColors[2];
								color.m_crLeft = arrayColors[3];
								m_arrayColors.push_back(color);
							}
						    break;
						}

						arrayColors.clear();
					}
					break;
				default:
					{
						strValue += szColors[i];
					}
				    break;
				}
			}
		}

	private:
		void _drawBorder(CDC* pDC, LONG lLeft, LONG lTop, LONG lRight, LONG lBottom, const FourWayBorderColor& colors)
		{
			if (BorderStyle() > PS_SOLID)
			{
				CPen penTop		(BorderStyle(), 1, colors.m_crTop);
				CPen penLeft	(BorderStyle(), 1, colors.m_crLeft);
				CPen penRight	(BorderStyle(), 1, colors.m_crRight);
				CPen penBottom	(BorderStyle(), 1, colors.m_crBottom);

				--lRight;
				--lBottom;

				CPen* pOldPen = pDC->SelectObject(&penTop);
				pDC->MoveTo(lLeft, lTop);
				pDC->LineTo(lRight, lTop);

				pDC->SelectObject(&penRight);
				pDC->LineTo(lRight, lBottom);

				pDC->SelectObject(&penBottom);
				pDC->LineTo(lLeft, lBottom);

				pDC->SelectObject(&penLeft);
				pDC->LineTo(lLeft, lTop);

				pDC->SelectObject(pOldPen);
			}
			else
			{
				long& x = lLeft;
				long& y = lTop;
				long cx = lRight - lLeft;
				long cy = lBottom - lTop;
				pDC->FillSolidRect(x, y, cx - 1, 1, colors.m_crTop);
				pDC->FillSolidRect(x, y, 1, cy - 1, colors.m_crLeft);
				pDC->FillSolidRect(lRight, y, -1, cy, colors.m_crRight);
				pDC->FillSolidRect(x, lBottom, cx, -1, colors.m_crBottom);
			}
		}

		FourWayBorderColorArray m_arrayColors;

	private:
		void DefaultValue()
		{
			BorderWidth() = BorderStyle() = 0;
		}
	};
};